package com.liuguang.common.utils;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SignatureException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.Key;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName: JwtUtil
 * @Description：jwt工具类
 * @Author: wanghr
 * Date: 5:04 PM 2020/9/16
 * Version: 1.0
 */
public class JwtUtil {
    private static final Logger logger = LoggerFactory.getLogger(JwtUtil.class);

    private static final String AUTH = "auth";

    //Token 的默认过期时间 24小时
    private static final long DEFUALT_TIME = 86400000L;
    // remenberMe token 保存时间 30 天
    private static final long REMENBERME_TIME = 2592000000L;

    private static final Key KEY = Keys.secretKeyFor(SignatureAlgorithm.HS512);

    public static String createToken(Map<String, Object> map) {
        return createToken(map, false);
    }

    /**
     * 登录成功后，根据 authentication 创建 token 保存用户信息
     *
     * @params: [authentication, remenberMe]
     * @return: java.lang.String
     */
    public static String createToken(Map<String, Object> map, Boolean remenberMe) {

        Date exptrateTime = getExpirationTime(remenberMe);
        System.out.println("exptrateTime = " + exptrateTime);
//        logger.info("username:{}",username);
//        logger.info("auth:{}", auth);
//        HashMap<String, Object> map = new HashMap<>();
//        map.put(AUTH, auth);
        String username = (String) map.get("username");
        return Jwts
                .builder()
                .setSubject(username)
                .addClaims(map)
                .signWith(KEY)
                .setExpiration(exptrateTime)
                .compact();
    }

    /**
     * 获取 token 的过期时间
     */
    private static Date getExpirationTime(Boolean remenberMe) {
        long l = System.currentTimeMillis();
        if (remenberMe) {
            return new Date(l + REMENBERME_TIME);
        } else {
            return new Date(l + DEFUALT_TIME);
        }
    }

    /**
     * 验证 token 是否可以解析
     *
     * @params: [token]
     * @return: boolean
     */
    public static boolean validateTokenWithKey(String token,String key) {
        try {
            Jwts.parser()
                    .setSigningKey(key)
                    .parseClaimsJws(token)
                    .getBody();
            return true;
        } catch (ExpiredJwtException e) {
            logger.info("token 已过期");
            e.printStackTrace();
        } catch (MalformedJwtException e) {
            logger.info("MalformedJwtException ");
            e.printStackTrace();
        } catch (SignatureException e) {
            logger.info("Signature 解析异常");
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            logger.info("参数不正确");
            e.printStackTrace();
        }
        return false;
    }

    // 与上面的方法重复
    public static Map parseTokenWithKey(String token,String key) {
        Claims claims = Jwts.parser()
                .setSigningKey(key)
                .parseClaimsJws(token)
                .getBody();
        Date expiration = claims.getExpiration();
        String username = claims.getSubject();
        String auth = claims.get(AUTH, String.class);
        String[] auths = auth.split(",");
        ArrayList<String> list = new ArrayList<>(Arrays.asList(auths));

        HashMap<String, Object> map = new HashMap<>();
        map.put("auth", list);
        map.put("username", username);
        map.put("expiredTime", expiration);
        return map;
    }

    /**
     * 获取token的过期时间
     *
     * @params:
     * @return:
     */
    public static void getTokenExpiredTime(String token) {

    }

    public static String getJwtClaimKey() {
//        Base64.Encoder encoder = Base64.getEncoder();
//        byte[] encode = encoder.encode(KEY.getEncoded());
//        String base64EncodedKey = new String(encode);
//        System.out.println("base64EncodedKey = " + base64EncodedKey);

        String encodebyHutool = cn.hutool.core.codec.Base64.encode(KEY.getEncoded());
//        System.out.println("encodebyHutool = " + encodebyHutool);
        return encodebyHutool;
    }
}
